use crate::var::cmd;
use crate::var::dir::ROOT;
use anyhow::Result;
use async_std::fs::File;
use async_std::net::UdpSocket;
use bytes::{BufMut, BytesMut};
use log::{error, info};
use rmw_utf8::{decode, encode};
use std::fs;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

pub async fn init(port: u16) -> Result<()> {
  let mut root = ROOT.clone();
  root.push("mnt");
  fs::create_dir_all(&root).unwrap();

  let socket =
    UdpSocket::bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), port)).await?;

  info!("socket {:?}", socket.local_addr());

  let mut buf = BytesMut::with_capacity(1472);

  if true {
    let boot_ip = "47.104.79.244:34954";

    let file = "udp/README";

    buf.put_u8(cmd::GET);
    buf.put(&*encode(file.as_bytes()));

    socket.send_to(&buf, boot_ip).await?;
  }

  while let Ok((n, peer)) = socket.recv_from(&mut buf).await {
    if n > 0 {
      let cmd = buf[0];
      let data = &buf[1..n];
      match cmd {
        cmd::GET => {
          let fp = decode(data);
          info!("get {}", fp);
          match File::open(&root.clone().join(&fp)).await {
            Ok(file) => {
              info!("{:?}", file);
            }
            Err(err) => {
              error!("{} {:?}", fp, err)
            }
          }
        }
        _ => {
          info!("{} {} : {:?}", peer, cmd, data);
        }
      }
    }
    //socket.send_to(&buf[..n], &peer).await?;
  }

  Ok(())
}
